package mop.controller;
import java.sql.Timestamp;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;

import mop.exception.IllegalIdException;
import mop.model.World;
import mop.model.task.TaskInterface;
import mop.model.task.comparator.TaskDeadlineComparator;
import mop.model.task.comparator.TaskDurationComparator;
import mop.model.task.filter.DurationFilter;
import mop.model.task.filter.StateFilter;
import mop.model.task.filter.TaskTypeFilter;
import mop.model.task.tasktype.TaskType;
import mop.model.task.tasktype.TaskTypeInterface;
import mop.util.filter.Filter;
import mop.util.filter.MaxCutOffFilter;
import mop.util.sort.MergeSort;
import mop.util.sort.Sort;

/**
 * Handler for the focus work use case
 * @author MOP Team 7
 */
public class FocusWorkController extends UseCaseController{
	
	
	/**
	 * Constructor
	 * @param world	The world object
	 * @effect Call super constructor
	 * 	|super(world)
	 */
	public FocusWorkController(World world)
	{
		super(world);
	}
	

	/**
	 * Get a focus work list based on filters & sorters
	 * @param sorter		Sorter algorithm
	 * @param comparator	Comparator to use with sorter algorithm
	 * @param filtersBefore	Filters to use on list before sorting
	 * @param filtersAfter	Filters to use on list after sorting
	 * @return	Sorted & filtered list
	 */
	public List<TaskInterface> getFocusWorkList(Sort<TaskInterface> sorter, Comparator<TaskInterface> comparator, List<Filter<TaskInterface>> filtersBefore, List<Filter<TaskInterface>> filtersAfter){
		//retriever list with tasks
		List<TaskInterface> list = getUserTasks();
		list = filterList(list,filtersBefore);
		sorter.sort(list, comparator);
		list = filterList(list,filtersAfter);
		return list;
	}
	
	/**
	 * Filter a list with given filters
	 * @param list		List to filter
	 * @param filters	Filters to use on list, will be used in same sequence as they appear in list
	 * @return	
	 */
	private List<TaskInterface> filterList(List<TaskInterface> list, List<Filter<TaskInterface>> filters){
		for(Filter<TaskInterface> filter : filters){
			list = filter.filter(list);
		}
		return list;
	}
	
	/**
	 * 
	 * PREDIFINED LISTS
	 * 
	 */
	
	/**
	 * Get a list of tasks based on their duration
	 * @return List with tasks sorted on duration
	 */
	public List<TaskInterface> getDurationBasedFocus(Timestamp minimum, Timestamp maximum)
	{
		
		List<Filter<TaskInterface>> filtersBefore = new LinkedList<Filter<TaskInterface>>();
		filtersBefore.add(new DurationFilter(minimum,maximum));
		
		List<Filter<TaskInterface>> filtersAfter = new LinkedList<Filter<TaskInterface>>();

		return getFocusWorkList(new MergeSort<TaskInterface>(), new TaskDurationComparator(), filtersBefore, filtersAfter);
	}
	
	/**
	 * Get a list of tasks based on their deadline
	 * @return List with deadlines
	 */
	public List<TaskInterface> getDeadlineBasedFocus(int maximum)
	{
		List<Filter<TaskInterface>> filtersBefore = new LinkedList<Filter<TaskInterface>>();
		filtersBefore.add(new StateFilter("Available"));
		
		List<Filter<TaskInterface>> filtersAfter = new LinkedList<Filter<TaskInterface>>();
		filtersAfter.add(new MaxCutOffFilter<TaskInterface>(maximum));
		
		return getFocusWorkList(new MergeSort<TaskInterface>(), new TaskDeadlineComparator(), filtersBefore, filtersAfter);
	}
	
	/**
	 * Get a list of tasks based on their type, sorted by deadline
	 * @return List with deadlines
	 * @throws IllegalIdException 
	 */
	public List<TaskInterface> getTaskTypeBasedFocus(String typeid) throws IllegalIdException
	{
		TaskType type = getWorld().getTaskTypeDataBase().find(typeid);
	
		List<Filter<TaskInterface>> filtersBefore = new LinkedList<Filter<TaskInterface>>();
		filtersBefore.add(new StateFilter("Available"));
		filtersBefore.add(new TaskTypeFilter(type));
		List<Filter<TaskInterface>> filtersAfter = new LinkedList<Filter<TaskInterface>>();
		
		return getFocusWorkList(new MergeSort<TaskInterface>(), new TaskDeadlineComparator(), filtersBefore, filtersAfter);
	}

	/***************************************************************************
	 * 								Extras
	 ***************************************************************************/

        /**
	 * Return a list with all possible users
	 * @return A list of interfaces to users
	 */
        public List<TaskTypeInterface> getAllTaskTypes()
        {
            return super.getAllTaskTypes();
        }
	
	/***************************************************************************
	 * 								Visit
	 ***************************************************************************/
	
	/**
	 * Make a CallBack to the visitor
	 * @param v the visitor
	 */
	public void accept(ControllerVisitor v)
	{
		v.visit(this);
	}
	
	/***************************************************************************
	 * 								Acl
	 ***************************************************************************/
	
	@Override
	public String getAssetId() {
		return "FocusWork";
	}
}